﻿using System;
using NUnit.Framework;

namespace OpenWaves.UnitTests
{
    [TestFixture]
    public class StringExtensionsTests
    {
        [Test]
        public void Test()
        {
            Assert.That("Elo Melo".Truncate(6, TruncateOptions.WordBoundry), Is.EqualTo("Elo"));
            Assert.That("EloMelo".Truncate(6, TruncateOptions.WordBoundry), Is.EqualTo("EloMel"));
        }

        [Test]
        public void TestTruncateDoesNotChangeValuesShorterThenMaxLength()
        {
            Assert.That("abcdefgh", Is.EqualTo("abcdefgh".Truncate(100)));
            Assert.That("abcdefgh", Is.EqualTo("abcdefgh".Truncate(100, TruncateOptions.AddEllipsis)));
            Assert.That("abcdefgh", Is.EqualTo("abcdefgh".Truncate(100, CharacterWidth.Constant, TruncateOptions.AddEllipsis)));
        }

        [Test]
        public void TestWordBoundryWithEllipsisTruncate()
        {
            var truncated = "Ala ma kota a kot ma     ale i takie tam  ".Truncate(20,
                                    TruncateOptions.WordBoundry |
                                    TruncateOptions.AddEllipsis);
            Assert.AreEqual("Ala ma kota a kot ma…", truncated);
        }

        [Test]
        public void TestTruncatingEmtpyString()
        {
            Assert.AreEqual(string.Empty, "    ".Truncate(1, TruncateOptions.WordBoundry));
            Assert.AreEqual(string.Empty,string.Empty.Truncate(5));
            Assert.AreEqual(string.Empty, string.Empty.Truncate(5,TruncateOptions.AddEllipsis));
            Assert.AreEqual(string.Empty, string.Empty.Truncate(5, TruncateOptions.AddEllipsis|TruncateOptions.PreserveTrailingWhiteSpace));
            Assert.AreEqual(string.Empty, string.Empty.Truncate(5, TruncateOptions.AddEllipsis | TruncateOptions.WordBoundry));
            Assert.AreEqual("…", "  ".Truncate(1, TruncateOptions.WordBoundry | TruncateOptions.AddEllipsis));

        }

        [Test]
        public void TestWordBoundryOnlyTruncate()
        {
            var truncated = "Ala ma kota a kot ma     ale i takie tam  ".Truncate(20, TruncateOptions.WordBoundry);
            Assert.AreEqual("Ala ma kota a kot ma", truncated);
        }

        [Test]
        public void TestWordBoundryWithPreserveTrailingWhiteSpaceTruncate()
        {
         

            var truncated = "Ala ma kota a kot ma     ale i takie tam  "
                .Truncate(23, TruncateOptions.WordBoundry |TruncateOptions.PreserveTrailingWhiteSpace);
            Assert.AreEqual("Ala ma kota a kot ma   ", truncated);
        }

        [Test]
        public void TestWordBoundryWithPreserveTrailingWhiteSpaceTruncateAndEllipsis()
        {
            var truncated = "Ala ma kota a kot ma     ale i takie tam  "
                .Truncate(23, TruncateOptions.WordBoundry |TruncateOptions.PreserveTrailingWhiteSpace |TruncateOptions.AddEllipsis);
            Assert.AreEqual("Ala ma kota a kot ma   …",truncated);

            var truncated2 = "Ala ma kota a kot ma     ale i takie tam  "
               .Truncate(23, TruncateOptions.WordBoundry| TruncateOptions.AddEllipsis);
            Assert.AreEqual("Ala ma kota a kot ma…", truncated2);
        }


        [Test]
        public void TestTruncateRemovesCharactersExceedingMaxLength()
        {
            Assert.That("abcd", Is.EqualTo("abcdefgh".Truncate(4)));            
        }

        [Test]
        public void TestTruncateAddsEllipsisIfTruncating()
        {
            Assert.That("abcd…", Is.EqualTo("abcdefgh".Truncate(4, TruncateOptions.AddEllipsis)));
        }

        [Test]
        public void TestTruncateUsesCharacterWidthStatisticsWhenTruncating()
        {
            Assert.That("abc", Is.EqualTo("abcabc".Truncate(6, new CharacterWidthStatisticsStub(), TruncateOptions.None)));
        }

        [Test]
        public void TestProportionalCharacterWidthStatisticsReturnPredictableWidths()
        {
            Assert.That(CharacterWidth.Proportional.GetCharacterWidth('w') > CharacterWidth.Proportional.GetCharacterWidth('a'));
            Assert.That(CharacterWidth.Proportional.GetCharacterWidth('a') > CharacterWidth.Proportional.GetCharacterWidth('t'));
            Assert.That(CharacterWidth.Proportional.GetCharacterWidth('t') > CharacterWidth.Proportional.GetCharacterWidth('l'));
        }

        private class CharacterWidthStatisticsStub : ICharacterWidthStatisticsProvider
        {
            public double GetCharacterWidth(char ch)
            {
                switch(ch)
                {
                    case 'a':
                        return 1;
                    case 'b':
                        return 2;
                    case 'c':
                        return 3;
                    default:
                        throw new ArgumentOutOfRangeException();

                }
            }
        }
    }
}
